﻿#ifndef __SS_ANY_H__
#define __SS_ANY_H__
#include <typeinfo>

namespace StarSeeker
{

class ssAny  
{
private:
	//基类声明
	class IValue
	{
	public:
		virtual const std::type_info& GetType() = 0;
		virtual IValue* Clone() = 0;
	};
	//子类扩展为模板类
	template<typename T>
	class ssValue : public IValue
	{
	public:
		ssValue(const T& val)
			:_value(val)
		{
		}
		virtual const std::type_info& GetType()
		{
			return typeid(T);
		}
		virtual IValue* Clone()
		{
			//拷贝一份数据
			return new ssValue<T>(_value);
		}
		T& Get()
		{
			return _value;
		}
		const T& Get() const
		{
			return _value;
		}
		unsigned int Size() const
		{
			return sizeof(T);
		}
	private:
		//模板类对象中存储着any数据
		T    _value;
	};

public:
    ssAny()  
		:m_pValue(0)
    {
    }
    template<typename T>
    ssAny(const T& t)
        :m_pValue(new ssValue<T>(t))
    {
    }
	ssAny(const ssAny& ma)
        :m_pValue(ma.IsEmpty()?0:ma.m_pValue->Clone())
    {
    }  
    virtual ~ssAny()
    {
        if ( m_pValue )
        {
            delete m_pValue;
			m_pValue = 0;
        }
    }
    ssAny& Swap(ssAny& ma)
    {
        //交换两个对象的地址，避免了重新申请释放内存，提高效率
        std::swap( ma.m_pValue, m_pValue);
        return *this;
    }
    template<typename T>
    ssAny& operator=(const T& val)
    {  
        //重载=操作符，先是构造一个ssAny对象，Awap交换对象指针后，原来需要释放的那个指针就到了临时对象ssAny(val)中
        //函数返回后，临时变量自动析构，调用了析构函数释放这块内存，不会造成内存泄露。
        ssAny(val).Swap(*this);
        return *this;
    }
    bool IsEmpty() const
    {
        return !m_pValue;
    }
	const char* GetType() const
	{
		if (m_pValue)
		{
			return m_pValue->GetType().name();
		}
		else
		{
			return "null";
		}
	}
	template<typename T>
	T* Get()
	{
		if (m_pValue)
		{
			if (m_pValue->GetType() == typeid(T))
			{
				return &(reinterpret_cast<ssValue<T>*>(m_pValue)->Get());
			}
		}
		return 0;
	}
	template<typename T>
	T Clone()
	{
		if (m_pValue)
		{
			if (m_pValue->GetType() == typeid(T))
			{
				return (reinterpret_cast<ssValue<T>*>(m_pValue)->Get());
			}
		}
		return T();
	}

private:
    IValue* m_pValue;
};

}
#endif
